package com.wanhe.viewconf.views.group;

import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.support.annotation.Keep;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import com.orhanobut.logger.Logger;
import com.wanhe.base.model.disgn.Event;
import com.wanhe.base.model.disgn.ViewEvent;
import com.wanhe.base.model.disgn.ViewItem;
import com.wanhe.base.util.ObjectUtil;
import com.wanhe.viewconf.adapter.MenuPageItemAdapter;
import com.wanhe.viewconf.views.child.BaseXYView;
import com.wanhe.viewconf.views.child.MealBookChildItemView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

/**
 * PAD用于存储坐标控件的父控件
 *
 * @author 陈德基
 *         create at 2016/12/26 9:55
 */
public class CoordinateViewGroup extends FrameLayout {

	public static final String	TAG	= "CoordinateViewGroup";

	private int					viewWidth;
	private int					viewHeight;
	private float				mScale;

	private MenuPageItemAdapter	mAdapter;

	private DataSetObserver		mDataSetObserver;
	/**
	 * 判断页面是否初始化过
	 * @author 陈德基
	 * @time 2017/8/2 19:14
	 */
	private boolean isReady;

	@Keep
	public CoordinateViewGroup(Context context) {
		this(context, null);
	}

	@Keep
	public CoordinateViewGroup(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	/**
	 * 通过使用适配器对组件中的控件进行添加
	 *
	 * @author 陈德基
	 *         create at 2016/12/24 14:20
	 */
	@Keep
	public void setAdapter(MenuPageItemAdapter itemAdapter) {
		if (mAdapter != null && mDataSetObserver != null) {
			mAdapter.unregisterDataSetObserver(mDataSetObserver);
		}
		this.mAdapter = itemAdapter;
		mDataSetObserver = new DataSetObserver() {
			@Override
			public void onChanged() {
				removeAllViews();
				initChild();
			}

			@Override
			public void onInvalidated() {
			}
		};
		this.mAdapter.registerDataSetObserver(mDataSetObserver);
		initChild();

	}

	private Map<Integer, List<BaseXYView>>	viewMap		= new HashMap<>();		// 控件映射表
	private List<Event>						pageEvents	= new ArrayList<>();	// 页面事件缓存列表

	/**
	 * File Name:CoordinateViewGroup.java<br/>
	 * Package Name:com.wanhe.viewconf.views.group<br/>
	 * Date:2017/7/11 10:15<br/>
	 * author:chendeji<br/>
	 * desc: 用于接受子控件发送的事件信息<br/>
	 * Copyright (c) 2017/7/11, 781571323@qq.com All Rights Reserved.
	 *
	 */
	public void receiveEvent(final ViewEvent viewEvent) throws IllegalArgumentException {
		if (!ObjectUtil.checkObjectList(viewEvent.mEvents)) {
			throw new IllegalArgumentException("event data can't not be null");
		}

		Observable.just(viewEvent).flatMap(new Function<ViewEvent, ObservableSource<Event>>() {
			@Override
			public ObservableSource<Event> apply(@NonNull ViewEvent event) throws Exception {
				return Observable.fromIterable(event.mEvents);
			}
		}).flatMap(new Function<Event, ObservableSource<EventViewMap>>() {
			@Override
			public ObservableSource<EventViewMap> apply(@NonNull Event event) throws Exception {
				List<EventViewMap> maps = new ArrayList<>();
				List<BaseXYView> views = CoordinateViewGroup.this.viewMap.get(event.getCid());
				if (ObjectUtil.checkObjectList(views)) {
					EventViewMap map = null;
					for (int i = 0; i < views.size(); i++) {
						BaseXYView baseXYView = views.get(i);
						map = new EventViewMap();
						map.event = event;
						if (ObjectUtil.checkObject(viewEvent.dish)){
							map.event.getArgs().setDishID(viewEvent.dish.getDish_guid());
						}
						map.event.fromCid = viewEvent.getFromCid();
						map.view = baseXYView;
						maps.add(map);
					}
					return Observable.fromIterable(maps);
				}
				return null;
			}
		}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
				.subscribe(new Observer<EventViewMap>() {
					@Override
					public void onSubscribe(@NonNull Disposable d) {
					}

					@Override
					public void onNext(@NonNull EventViewMap eventViewMap) {
						eventViewMap.view.onEvent(eventViewMap.event, viewEvent.coor);
					}

					@Override
					public void onError(@NonNull Throwable e) {
						Logger.t(TAG).e(e.getMessage());
					}

					@Override
					public void onComplete() {
					}
				});
	}

	/**
	 * File Name:CoordinateViewGroup.java<br/>
	 * Package Name:com.wanhe.viewconf.views.group<br/>
	 * Date:2017/7/14 14:02<br/>
	 * author:chendeji<br/>
	 * desc: 对外暴露的操作，外部具体实现<br/>
	 * Copyright (c) 2017/7/14, 781571323@qq.com All Rights Reserved.
	 *
	 */
	public interface OnRequireDismissListener {
		void onCancleRequire();
	}

	public void setListener(OnRequireDismissListener listener) {
		this.listener = listener;
	}

	private OnRequireDismissListener listener;

	/**
	 * Methor Name:用于执行整个隐藏的功能<br/>
	 * Package Name:com.wanhe.viewconf.views.group<br/>
	 * Date:2017/7/14 14:01<br/>
	 * author:chendeji<br/>
	 * desc: <br/>
	 * Copyright (c) 2017/7/14, 781571323@qq.com All Rights Reserved.
	 *
	 * @param
	 * @return
	 *
	 */
	public void dismiss() {
		if (listener != null) {
			listener.onCancleRequire();
		}
	}

	/**
	 * File Name:CoordinateViewGroup.java<br/>
	 * Package Name:com.wanhe.viewconf.views.group<br/>
	 * Date:2017/7/11 10:45<br/>
	 * author:chendeji<br/>
	 * desc: 用于表达映射关系的辅助类<br/>
	 * Copyright (c) 2017/7/11, 781571323@qq.com All Rights Reserved.
	 *
	 */
	private class EventViewMap {
		Event		event;
		BaseXYView	view;
	}

	private void initChild() {
		int count = this.mAdapter.getCount();
		for (int i = 0; i < count; i++) {
			ViewItem item = (ViewItem) this.mAdapter.getItem(i);
			int cid = item.getCid();

			/**
			 * 检测页面是否有初始化要执行的事件，如果有存储到另外一个缓存列表中
			 * ，等到页面加载结束后，执行初始化事件操作
			 *
			 * @author 陈德基
			 * @time 2017/7/13 14:13
			 */
			if (item.getType().equals("pageEvents")) {
				pageEvents.addAll(item.getEvents());
				continue;
			}

			BaseXYView childView = (BaseXYView) this.mAdapter.getView(i, null, this);
			if (childView == null) {
				continue;
			}

			/**
			 * 初始化控件表，方便后面根据设计器给出的viewid查找到某一部分的控件数组
			 * 
			 * @author 陈德基
			 * @time 2017/7/11 10:51
			 */
			if (this.viewMap.containsKey(cid)) {
				this.viewMap.get(cid).add(childView);
			} else {
				List<BaseXYView> views = new ArrayList<>();
				views.add(childView);
				this.viewMap.put(cid, views);
			}

			this.addView(childView);
		}
	}

	/**
	 * Methor Name:initMealBookPage<br/>
	 * Package Name:com.wanhe.viewconf.views.group<br/>
	 * Date:2017/7/13 14:22<br/>
	 * author:chendeji<br/>
	 * desc: 页面需要进行初始化操作的时候<br/>
	 * Copyright (c) 2017/7/13, 781571323@qq.com All Rights Reserved.
	 *
	 * @param
	 * @return
	 *
	 */
	public void initMealBookPage() {
		if (ObjectUtil.checkObjectList(this.pageEvents)) {
			ViewEvent event = new ViewEvent();
			List<Event> events = new ArrayList<>();
			events.addAll(this.pageEvents);
			this.pageEvents.clear();
			event.mEvents = events;
			receiveEvent(event);
		}

		/**
		 * 如果页面没有初始化过，并且有初始化绑定的需求，需要进行一次初始化操作
		 * @author 陈德基
		 * @time 2017/8/2 19:15
		 */
		if (!isReady){
			readyChilds();
		} else {
			/**
			 * 调用所有子控件的resume方法，重新进行显示内容
			 * @author 陈德基
			 * @time 2017/7/27 9:35
			 */
			resumeChilds();
		}
	}

	private void readyChilds(){
		Observable.just(viewMap).flatMap(
				new Function<Map<Integer, List<BaseXYView>>, ObservableSource<BaseXYView>>() {
					@Override
					public ObservableSource<BaseXYView> apply(
							@NonNull Map<Integer, List<BaseXYView>> integerListMap)
							throws Exception {
						List<BaseXYView> xyViews = new ArrayList<>();
						for (Map.Entry<Integer, List<BaseXYView>> entry : integerListMap
								.entrySet()) {
							xyViews.addAll(entry.getValue());
						}
						return Observable.fromIterable(xyViews);
					}
				}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
				.subscribe(new Observer<BaseXYView>() {
					@Override
					public void onSubscribe(@NonNull Disposable d) {

					}

					@Override
					public void onNext(@NonNull BaseXYView view) {
						MealBookChildItemView childItemView = (MealBookChildItemView) view;
						childItemView.callSelfEvent("ready");
					}

					@Override
					public void onError(@NonNull Throwable e) {

					}

					@Override
					public void onComplete() {
						isReady = !isReady;
						/**
						 * 调用所有子控件的resume方法，重新进行显示内容
						 * @author 陈德基
						 * @time 2017/7/27 9:35
						 */
						resumeChilds();
					}
				});
	}


	private void resumeChilds() {
		final Event resumeEvent = new Event();
		resumeEvent.setCop("resume");
		Observable.just(viewMap).flatMap(
				new Function<Map<Integer, List<BaseXYView>>, ObservableSource<BaseXYView>>() {
					@Override
					public ObservableSource<BaseXYView> apply(
							@NonNull Map<Integer, List<BaseXYView>> integerListMap)
							throws Exception {
						List<BaseXYView> xyViews = new ArrayList<>();
						for (Map.Entry<Integer, List<BaseXYView>> entry : integerListMap
								.entrySet()) {
							xyViews.addAll(entry.getValue());
						}
						return Observable.fromIterable(xyViews);
					}
				}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
				.subscribe(new Consumer<BaseXYView>() {
					@Override
					public void accept(@NonNull BaseXYView view) throws Exception {
						view.onEvent(resumeEvent, null);
					}
				});
	}

	/**
	 * Methor Name:pauseChildItems<br/>
	 * Package Name:com.wanhe.viewconf.views.group<br/>
	 * Date:2017/7/26 11:11<br/>
	 * author:chendeji<br/>
	 * desc: 用于及时回收消耗资源较高的控件的回调<br/>
	 * Copyright (c) 2017/7/26, 781571323@qq.com All Rights Reserved.
	 *
	 * @param 
	 * @return 
	 * 
	 */
	public void pauseChildItems() {
		final Event pauseEvent = new Event();
		pauseEvent.setCop("pause");
		Observable.just(viewMap).flatMap(
				new Function<Map<Integer, List<BaseXYView>>, ObservableSource<BaseXYView>>() {
					@Override
					public ObservableSource<BaseXYView> apply(
							@NonNull Map<Integer, List<BaseXYView>> integerListMap)
							throws Exception {
						List<BaseXYView> xyViews = new ArrayList<>();
						for (Map.Entry<Integer, List<BaseXYView>> entry : integerListMap
								.entrySet()) {
							xyViews.addAll(entry.getValue());
						}
						return Observable.fromIterable(xyViews);
					}
				}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
				.subscribe(new Consumer<BaseXYView>() {
					@Override
					public void accept(@NonNull BaseXYView view) throws Exception {
						view.onEvent(pauseEvent, null);
					}
				});
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		viewHeight = MeasureSpec.getSize(heightMeasureSpec);
		viewWidth = MeasureSpec.getSize(widthMeasureSpec);
		setMeasuredDimension(viewWidth, viewHeight);
		int count = getChildCount();
		for (int i = 0; i < count; i++) {
			View child = getChildAt(i);
			if (child.getVisibility() == GONE) {
				continue;
			}
			if (child instanceof BaseXYView) {
				BaseXYView xyScaleView = (BaseXYView) child;
				if (xyScaleView.getViewStatu() == BaseXYView.VIEW_CLEAR)
					continue;
				childMeasure(xyScaleView);
			}
		}
	}

	private void childMeasure(BaseXYView scaleView) {
		double widthScale = scaleView.getWidthPT();
		double heigthScale = scaleView.getHeightPT();
		double childViewWidth = 0;
		double childViewHeight = 0;

		/**
		 * 需要对设计器传回的数据进行再次的加工处理
		 *
		 * @author 陈德基
		 *         create at 2017/5/27 11:26
		 */
		childViewHeight = viewHeight * heigthScale;
		if (widthScale > 0) {
			double screenWidth = viewHeight * mScale;
			childViewWidth = viewHeight * (viewWidth / screenWidth) * widthScale;
			int newWidthMeasure = MeasureSpec.makeMeasureSpec((int) childViewWidth,
					MeasureSpec.EXACTLY);
			int newHeightMeasure = MeasureSpec.makeMeasureSpec((int) childViewHeight,
					MeasureSpec.EXACTLY);
			scaleView.measure(newWidthMeasure, newHeightMeasure);
		} else {
			int newWidthMeasure = MeasureSpec.makeMeasureSpec(viewWidth, MeasureSpec.UNSPECIFIED);
			int newHeightMeasure = MeasureSpec.makeMeasureSpec((int) childViewHeight,
					MeasureSpec.EXACTLY);
			scaleView.measure(newWidthMeasure, newHeightMeasure);
		}
		scaleView.setRealWidth(scaleView.getMeasuredWidth());
		scaleView.setRealHeight((int) childViewHeight);
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		int count = getChildCount();
		for (int i = 0; i < count; i++) {
			View child = getChildAt(i);
			if (child.getVisibility() == GONE) {
				continue;
			}
			if (child instanceof BaseXYView) {
				BaseXYView xyScaleView = (BaseXYView) child;
				if (xyScaleView.getViewStatu() == BaseXYView.VIEW_CLEAR)
					continue;
				if (xyScaleView.getViewStatu() == BaseXYView.VIEW_DIRTY
						|| xyScaleView.getViewStatu() == BaseXYView.VIEW_INIT) {
					xyScaleView.setViewStatu(BaseXYView.VIEW_CLEAR);
				}
				childLayout(xyScaleView);
			} else {
				child.layout(l, t, r, b);
			}
		}
	}

	private void childLayout(BaseXYView xyScaleView) {
		double topScale = xyScaleView.getTopPT();
		double leftScale = xyScaleView.getLeftPT();

		// 转换服务器原始坐标比例
		double top = (0.5 + topScale) * viewHeight;

		double screenWidth = viewHeight * mScale;
		double androidX = leftScale * viewHeight * (viewWidth / screenWidth);
		double left = viewWidth / 2 + androidX;

		int[] rect = xyScaleView.transpRect(left, top, (left + xyScaleView.getMeasuredWidth()),
				(top + xyScaleView.getMeasuredHeight()));

		xyScaleView.layout(rect[0], rect[1], rect[2], rect[3]);
	}

	@Keep
	public void setRealScale(float scale) {
		this.mScale = scale;
	}

}
